package com.eduagent.xwqeduagent.tools;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * Windows 终端操作工具
 * 注意：执行任意命令存在安全风险，请确保命令来源可靠或经过严格审查。
 */
public class TerminalOperationTool {

    private static final Logger logger = LoggerFactory.getLogger(TerminalOperationTool.class);
    // 为Windows cmd.exe 设置一个常用的编码，例如 GBK（简体中文）或 Charset.defaultCharset()
    // 如果你知道命令输出的确切编码，可以直接指定，例如 StandardCharsets.UTF_8 (如果命令输出UTF-8)
    private static final Charset CMD_CHARSET = Charset.forName("GBK"); // 或者尝试 Charset.defaultCharset()
    private static final long DEFAULT_TIMEOUT_SECONDS = 60; // 默认超时时间60秒

    @Tool(description = "在 Windows 终端中执行一个命令。警告：执行的命令拥有与本程序相同的权限，请谨慎使用。")
    public String executeTerminalCommand(
            @ToolParam(description = "要在终端中执行的命令字符串。例如 'dir C:\\' 或 'echo Hello'") String command,
            @ToolParam(description = "命令执行的超时时间（秒），如果小于等于0，则使用默认超时时间(" + DEFAULT_TIMEOUT_SECONDS + "秒)。") Long timeoutSeconds
    ) {
        StringBuilder output = new StringBuilder();
        Process process = null;
        long effectiveTimeout = (timeoutSeconds != null && timeoutSeconds > 0) ? timeoutSeconds : DEFAULT_TIMEOUT_SECONDS;

        // 安全提示：对命令进行基本的检查或清理可能有助于减少风险，但这不能完全替代对命令来源的信任。
        // 例如，可以限制允许执行的命令类型或路径。
        if (command == null || command.trim().isEmpty()) {
            logger.warn("接收到空命令。");
            return "错误：命令不能为空。";
        }
        logger.info("准备执行命令: {}，超时时间: {} 秒", command, effectiveTimeout);

        try {
            // 使用 cmd.exe /c 来执行命令，这允许使用shell内置命令和特性
            ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command);
            builder.redirectErrorStream(false); // 分开处理标准输出和标准错误

            process = builder.start();

            // 读取标准输出
            try (BufferedReader stdInputReader = new BufferedReader(new InputStreamReader(process.getInputStream(), CMD_CHARSET))) {
                String line;
                while ((line = stdInputReader.readLine()) != null) {
                    output.append(line).append(System.lineSeparator());
                }
            }

            // 读取标准错误
            StringBuilder errorOutput = new StringBuilder();
            try (BufferedReader stdErrorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), CMD_CHARSET))) {
                String line;
                while ((line = stdErrorReader.readLine()) != null) {
                    errorOutput.append(line).append(System.lineSeparator());
                }
            }

            // 等待命令执行完成，带超时
            if (!process.waitFor(effectiveTimeout, TimeUnit.SECONDS)) {
                // 命令超时
                process.destroyForcibly(); // 强制终止进程
                logger.warn("命令 '{}' 执行超时 ({} 秒)。", command, effectiveTimeout);
                output.append(System.lineSeparator()).append("错误: 命令执行超时 (").append(effectiveTimeout).append(" 秒)。");
                if (errorOutput.length() > 0) {
                    output.append(System.lineSeparator()).append("超时前的错误输出:").append(System.lineSeparator()).append(errorOutput);
                }
                return output.toString();
            }

            int exitCode = process.exitValue();
            output.append(System.lineSeparator()).append("命令执行完毕，退出码: ").append(exitCode);

            if (errorOutput.length() > 0) {
                output.append(System.lineSeparator()).append("错误流输出:").append(System.lineSeparator()).append(errorOutput);
            }

            if (exitCode != 0) {
                logger.warn("命令 '{}' 执行失败，退出码: {}", command, exitCode);
                // 错误信息已经在上面追加了
            } else {
                logger.info("命令 '{}' 执行成功。", command);
            }

        } catch (IOException e) {
            logger.error("执行命令 '{}' 时发生IO异常: {}", command, e.getMessage(), e);
            output.append(System.lineSeparator()).append("IO错误: ").append(e.getMessage());
        } catch (InterruptedException e) {
            logger.warn("命令 '{}' 执行被中断: {}", command, e.getMessage(), e);
            output.append(System.lineSeparator()).append("错误: 命令执行被中断。");
            // 恢复中断状态
            Thread.currentThread().interrupt();
        } catch (SecurityException e) {
            logger.error("执行命令 '{}' 时发生安全异常 (可能是权限不足): {}", command, e.getMessage(), e);
            output.append(System.lineSeparator()).append("安全错误: ").append(e.getMessage()).append(" (可能是权限不足)");
        } catch (Exception e) {
            logger.error("执行命令 '{}' 时发生未知错误: {}", command, e.getMessage(), e);
            output.append(System.lineSeparator()).append("未知错误: ").append(e.getMessage());
        } finally {
            if (process != null && process.isAlive()) {
                logger.warn("命令 '{}' 在方法结束时仍然存活，强制终止。", command);
                process.destroyForcibly();
            }
        }
        return output.toString().trim();
    }
}